package de.iritgo.skillfull.entity.command;

import java.awt.Point;
import java.awt.Rectangle;

import de.iritgo.skillfull.component.visitor.MoveAnimationVisitor;
import de.iritgo.skillfull.component.visitor.MoveFieldVisitor;
import de.iritgo.skillfull.component.visitor.MoveRotationVisitor;
import de.iritgo.skillfull.entity.Command;
import de.iritgo.skillfull.entity.Entity;
import de.iritgo.skillfull.entity.Entity.DST_FIELD;

public class MoveFieldCommand implements Command 
{
	public static final int STOP = 1;
	
	private Entity entity;
	private boolean done;
	private MoveFieldVisitor moveFieldVisitor;
	private Point oldPosition;
	private Point destPosition;
	private MoveRotationVisitor moveRotationVisitor;
	private DST_FIELD dstField;
	private boolean firstRun;

	private int special;

	private MoveAnimationVisitor moveAnimationVisitor;

	private float direction;

	private Rectangle validArea;
	
	public MoveFieldCommand (Entity entity, Point dest)
	{	
		this.firstRun = true;
		this.entity = entity;
		this.destPosition = dest;
		this.done = false;
	}
	
	public MoveFieldCommand (Entity entity, Entity.DST_FIELD dst)
	{	
		this.firstRun = true;
		this.dstField = dst;
		this.entity = entity;
		this.done = false;
	}

	public MoveFieldCommand (Entity entity, float direction, Rectangle validArea)
	{	
		this.firstRun = true;
		this.entity = entity;
		this.done = false;
		this.direction = direction;
		this.validArea = validArea;
	}

	public MoveFieldCommand(Entity entity, int special) 
	{
		this.firstRun = false;
		this.special = special;
		this.entity = entity;
		this.done = false;
		oldPosition = entity.getPosition ();
		this.moveFieldVisitor = new MoveFieldVisitor (special);
		this.moveRotationVisitor = new MoveRotationVisitor (special);
		this.moveAnimationVisitor = new MoveAnimationVisitor (special);
	}
	
	public String getName ()
	{
		return special == 0 ? "Move" : "Stop"; 
	}
	

	private Point getPositionByDstField(Entity.DST_FIELD dst, Point currentDst) 
	{
		int x = (int) currentDst.x;
		int y = (int) currentDst.y;
		int dstX = (int) currentDst.x;
		int dstY = (int) currentDst.y;
		
		switch (dst)
		{
			case NORTH:
			{
				dstY = (int) y - 32; //Get from MapService
				break;
			}
			case NORTHEAST:
			{
				dstY = (int) y - 32; //Get from MapService
				dstX = (int) x + 32; //Get from MapService
				break;
			}
			case EAST:
			{
				dstX = (int) x + 32; //Get from MapService
				break;
			}
			case SOUTHEAST:
			{
				dstY = (int) y + 32; //Get from MapService
				dstX = (int) x + 32; //Get from MapService
				break;
			}
			case SOUTH:
			{
				dstY = (int) y + 32; //Get from MapService
				break;
			}
			case SOUTHWEST:
			{
				dstY = (int) y + 32; //Get from MapService
				dstX = (int) x - 32; //Get from MapService
				break;
			}
			case WEST:
			{
				dstX = (int) x - 32; //Get from MapService
				break;
			}
			case NORTHWEST:
			{
				dstY = (int) y - 32; //Get from MapService
				dstX = (int) x - 32; //Get from MapService
				break;
			}
		}
		Point dstPosition = new Point (dstX, dstY);
		return dstPosition;
	}

	@Override
	public boolean canPerform () 
	{
		return true;
	}

	@Override
	public void perform (int delta) 
	{
		if (firstRun)
		{
			firstRun = false;
			oldPosition = entity.getPosition ();

			if (dstField != null)
			{
				this.destPosition = getPositionByDstField (dstField, oldPosition);
				this.moveFieldVisitor = new MoveFieldVisitor (destPosition);
				this.moveRotationVisitor = new MoveRotationVisitor (destPosition);
				this.moveAnimationVisitor = new MoveAnimationVisitor (false);
			}
			else if (validArea != null)
			{
				this.moveFieldVisitor = new MoveFieldVisitor (direction, validArea);
				this.moveRotationVisitor = new MoveRotationVisitor (direction, validArea);
				this.moveAnimationVisitor = new MoveAnimationVisitor (false);
				
			}
			else
			{
				this.moveFieldVisitor = new MoveFieldVisitor (destPosition);
				this.moveRotationVisitor = new MoveRotationVisitor (destPosition);
				this.moveAnimationVisitor = new MoveAnimationVisitor (false);
			}
		}
		entity.accept (moveFieldVisitor);
		entity.accept (moveRotationVisitor);
		entity.accept (moveAnimationVisitor);
		done = moveFieldVisitor.isDone ();
	}
	
	public void stop() 
	{
		done = true;
	}

	@Override
	public Command getUndoCommand () 
	{
		if (special == STOP || dstField == null)
		{
			return new MoveFieldCommand (entity, special);
		}
		
		int pos = dstField.ordinal ();
		pos = pos + 4;
		if (pos > 8)
		{
			pos = pos - 8;
		}
		return new MoveFieldCommand (entity, Entity.DST_FIELD.values()[pos]);
	}

	@Override
	public boolean isDone () 
	{
		return done;
	}
}
